import java.util.*;
import javax.crypto.*;
import javax.crypto.spec.*; 
import java.security.*;

public class Mode
{
	public Mode() {}
	
	public byte[] GetKeyFromString(String key) throws Exception
	{
		byte[] bytesOfKey = key.getBytes("UTF-8");
		MessageDigest md = MessageDigest.getInstance("MD5");
		return md.digest(bytesOfKey);
	}
        
        public byte[] GetKeyFromBytes(byte[] key) throws Exception
	{
		byte[] bytesOfKey = key;
		MessageDigest md = MessageDigest.getInstance("MD5");
		return md.digest(bytesOfKey);
	}
	
	public byte[] Encrypt(byte[] key, byte[] IV, byte[] plainText) throws Exception
	{
		DESKeySpec key1 = new DESKeySpec(Arrays.copyOfRange(key, 0, 8));
		DESKeySpec key2 = new DESKeySpec(Arrays.copyOfRange(key, 8, 16));
		
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		
		SecretKey sKey1 = keyFactory.generateSecret(key1);
		SecretKey sKey2 = keyFactory.generateSecret(key2);
		
		return Encrypt(sKey1, sKey2, IV, plainText);
	}
	
	public byte[] Encrypt(SecretKey key1, SecretKey key2, byte[] IV, byte[] plainText) throws Exception
	{
		throw new Exception("Encryption not implemented");
	}
	
	public byte[] Decrypt(byte[] key, byte[] IV, byte[] plainText) throws Exception
	{
		DESKeySpec key1 = new DESKeySpec(Arrays.copyOfRange(key, 0, 8));
		DESKeySpec key2 = new DESKeySpec(Arrays.copyOfRange(key, 8, 16));
		
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		
		SecretKey sKey1 = keyFactory.generateSecret(key1);
		SecretKey sKey2 = keyFactory.generateSecret(key2);
		
		return Decrypt(sKey1, sKey2, IV, plainText);
	}
	
	public byte[] Decrypt(SecretKey key1, SecretKey key2, byte[] IV, byte[] plainText) throws Exception
	{
		throw new Exception("Decryption not implemented");
	}
	
	protected byte[] XOR(byte[] a, byte[] b) throws Exception
	{
		if (a.length != b.length)
			throw new Exception("CBC XOR: size of a != to size of b");
			
		byte[] result = new byte[a.length];

		for (int i = 0; i < result.length; i++)
		{
			result[i] = (byte)(a[i] ^ b[i]);
		}
		
		return result;
	}
	
	protected void ReplaceBlock(byte[] Container, byte[] newBlock, int startIndex)
	{
		int length = newBlock.length;
		for (int i = startIndex; i < startIndex + length; i++)
		{
			Container[i] = newBlock[i - startIndex];
		}
	}
	
	
}